<?php
/* 
 * 支付宝支付
 * @author wyb
 */
namespace Api\Extend\Payment;
class Alipay {
    
    private $_appid = '';
    
    private $_url = 'https://openapi.alipay.com/gateway.do';
	
    private $_notify_url = 'http://w3.newbeemall.com/zt_forward/notify.php?payment=alipay';
    
    private $_seller_id = '';
    
    private $_private_key_path = ''; //rsa密匙路径
    
    private $_public_key = ''; //rsa公匙路径
    
    private $_data = array(); //请求的数据
    
    private $_customs = '';

    private $_enterprise_code = '';

    private $_customs_name = '';

    private $_sign_key = '';

    private $_pid = '';

    public function __construct( $conf ) {
		//print_r( $conf );die;
        $this->_private_key_path = SITE_FILE . trim( $conf['private_key_path'] );
		$this->_appid = trim( $conf['app_id'] );
        $this->_pid = trim( $conf['pid'] );
		$this->_seller_id = trim( $conf['account'] );
        $this->_customs = trim( $conf['port'] );
        $this->_enterprise_code = trim( $conf['enterprise_code'] );
        $this->_customs_name = trim( $conf['customs_name'] );
        $this->_sign_key = trim( $conf['sign_key'] );
        $this->_public_key = trim( $conf['public_key'] );
    }
    
    /**
     * 生成支付字符串
     * @return type
     */
    public function pay( $order_info ) {
            $this->_data = array(
                    'app_id' => $this->_appid, //应用APPID
					'method' => 'alipay.trade.page.pay',
                    'charset' => 'utf-8',//请求编码
					'sign_type' => 'RSA',
					'timestamp' => date('Y-m-d H:i:s'),
					'version' => '1.0',
                    'return_url' => $order_info['notify_url'] ? $order_info['notify_url'] : $this->_notify_url,
                    'notify_url' => $order_info['notify_url'] ? $order_info['notify_url'] : $this->_notify_url,
					'biz_content' => array(
						'subject' => $order_info['pay_body'],
						'out_trade_no' => $order_info['ref'],
						'total_amount' => $order_info['amount_total'],
						'product_code' => 'FAST_INSTANT_TRADE_PAY',
					)
            );
            $this->_data .= '&sign=' . urlencode( $this->_aign() );
			header('Location:' .$this->_url . '?' . $this->_data );
            
    }
	
	/**
     * 手机端生成支付字符串
     * @return type
     */
    public function pay_mobile( $order_info ) {
            $this->_data = array(
                    'app_id' => $this->_appid, //应用APPID
                    'method' => 'alipay.trade.wap.pay',
                    'charset' => 'utf-8',//请求编码
                    'sign_type' => 'RSA',
                    'timestamp' => date('Y-m-d H:i:s'),
                    'version' => '1.0',
                    'return_url' => $order_info['notify_url'] ? $order_info['notify_url'] : $this->_notify_url,
                    'notify_url' => $order_info['notify_url'] ? $order_info['notify_url'] : $this->_notify_url,
                    'biz_content' => array(
                            'subject' => $order_info['pay_body'],
                            'out_trade_no' => $order_info['ref'],
                            'total_amount' => $order_info['amount_total'],
                            'product_code' => 'QUICK_WAP_PAY',
                    )
            );
            $this->_data .= '&sign=' . urlencode( $this->_aign() );
			header('Location:' .$this->_url . '?' . $this->_data );
            
    }
    
    /**
     * 签名价签
     * @return type
     */
    private function _aign() {
        ksort( $this->_data );
        reset( $this->_data );
        $aign_data = array();
        foreach( $this->_data  as $k => $v ) {
            $aign_data[] = trim($k).'='.trim(is_array($v)?json_encode($v):$v);
			$url_data[] = trim($k).'='.trim(is_array($v)?json_encode($v):urlencode($v));
        }
        $data = implode('&',$aign_data );
		$this->_data = implode('&',$url_data );
        $priKey = file_get_contents( $this->_private_key_path );
        $res = openssl_get_privatekey($priKey);
        ($res) or die('加签错误啦');
        openssl_sign( $data , $sign, $res);
        openssl_free_key($res);
        $sign = base64_encode($sign);
        return $sign;
    }
    
    function verify( $sign )  {
        ksort( $this->_data );
        reset( $this->_data );
        $aign_data = array();
        foreach( $this->_data  as $k => $v ) {
                $aign_data[] = trim($k).'='.trim($v).'';
        }
        $this->_data = implode('&',$aign_data );
        $res = "-----BEGIN PUBLIC KEY-----\n" .
               wordwrap($this->_public_key, 64, "\n", true) .
               "\n-----END PUBLIC KEY-----";
        $result = (bool)openssl_verify($this->_data, base64_decode($sign), $res);
        openssl_free_key($res);
        return $result;

    }
	
	/**
	 * 支付宝退款
	 */
	public function orderRefund( $order_data , $price) {
		$this->_data = array(
				'app_id' => $this->_appid, //应用APPID
				'method' => 'alipay.trade.refund',
				'charset' => 'utf-8',//请求编码
				'sign_type' => 'RSA',
				'timestamp' => date('Y-m-d H:i:s'),
				'version' => '1.0',
				'biz_content' => array(
					'out_trade_no' => $order_data['ref'],
					'refund_amount' => $price
				)
		);
		$this->_data .= '&sign="' . urlencode( $this->_aign() );// . '"&sign_type="RSA"';
		$result = json_decode( $this->_send( $this->_url . '?' . $this->_data ) , true );
		if( $result ) {
			//支付成功
			if( $result['alipay_trade_refund_response']['code'] == 10000 ) {
				return array( 'msg' => '退款成功' , 'status' => true );
			} else { //支付失败
				return array( 'msg' => "code：". $result['alipay_trade_refund_response']['sub_code'] . " 错误描述：".$result['alipay_trade_refund_response']['sub_msg'] , 'status' => false );
			}
		} else {
			return array( 'msg' => '支付异常，请联系客服！' , 'status' => false );
		}
	}

    /**
     * 退款查询
     */
    public function refundQuery( $order_data ) {
        $this->_data = array(
                'app_id' => $this->_appid, //应用APPID
                'method' => 'alipay.trade.fastpay.refund.query',
                'charset' => 'utf-8',//请求编码
                'sign_type' => 'RSA',
                'timestamp' => date('Y-m-d H:i:s'),
                'version' => '1.0',
                'biz_content' => array(
                    'out_trade_no' => $order_data['ref'],
                    'out_request_no' => $order_data['payment_no']
                )
        );
        $this->_data .= '&sign="' . urlencode( $this->_aign() );// . '"&sign_type="RSA"';
        $result = json_decode( $this->_send( $this->_url . '?' . $this->_data ) , true );
        if( $result ) {
            $msg = '';
            //退款成功
            if( $result['alipay_trade_fastpay_refund_query_response']['code'] == 10000 && $result['alipay_trade_fastpay_refund_query_response']['msg'] == 'Success') {
                $state = 7;
            } else { //退款失败
                $state = 6;
                $msg = $result['alipay_trade_fastpay_refund_query_response']['sub_msg'];
            }
            //信息修改
            M('order')->save(array('state' => $state , 'id' => $order_data['id'] , 'refund_query_error' => $msg ));
            $order_data['state'] = $state;
            $order_data['refund_query_error'] = $msg;
            //推送给第三方用户
            D('Common/OrderPaySend')->refundSendInfo( $order_data );
        } else {
            //退款异常
            M('order')->save(array('state' => 5 , 'id' => $order_data['id']));
        }
    }
    
    /**
     * 支付回调
     */
    public function notify( $data ) {
        if( !$data ) exit( 'error' );
        //签名认证
        $sign = $data['sign'];
        unset( $data['sign'] );
        unset( $data['sign_type'] );
        $this->_data = $data;
        if( $this->verify( $sign ) === false ) return array('status' => 'error');
		return array('total_fee' => $data['total_amount'], 'payment_no' => $data['trade_no'] , 'order_sn' => $data['out_trade_no'] ,'status' => 'success');
    }

    /**
     * 支付宝清关
     */
    public function clearance( $data ) {
        $out_request_nos = date('YmdHis').rand(100,999);
        $this->_data = array(
                'service' => 'alipay.acquire.customs',
                'partner' => $this->_pid,
                '_input_charset' => 'UTF-8',//请求编码
                'out_request_no' => $out_request_nos, //报关流水号
                'trade_no' => $data['transaction_id'], //交易流水号
                'merchant_customs_code' => $this->_enterprise_code,
                'amount' => $data['payamount'], //报关金额
                'customs_place' => $this->_customs, //海关编号
                'merchant_customs_name' => $this->_customs_name //企业名称
        );
        $getData = $this->_querySign();
        $return_data = array();
        if( $getData['is_success'] == 'F' ) {
            $return_data = array(
                'state' => 1 , 'msg' => '报关接口异常' , 'status' => false
            );
        } else if( $getData['response']['alipay']['result_code'] == 'SUCCESS' ) {
            M('order')->save(array('id' => $data['id'] , 'alipay_out_request_nos' => $out_request_nos));
            $return_data = array(
                'state' => 2 , 'msg' => '' , 'status' => true
            );
        } else if( $getData['response']['alipay']['result_code'] == 'FAIL' ) {
            $return_data = array(
                'state' => 1 , 'msg' => $getData['response']['alipay']['detail_error_des'] , 'status' => false
            );
        }
        return $return_data;
    }

    /**
     * 清关查询
     */
    public function clearanceSelect( $data ) {
        $this->_data = array(
            'service' => 'alipay.overseas.acquire.customs.query',
            'partner' => $this->_pid,
            '_input_charset' => 'UTF-8', 
            'out_request_nos' => $data['alipay_out_request_nos']
        );
        $getData = $this->_querySign();
        $return_data = array();
        if( $getData['is_success'] == 'F' ) {
            $return_data = array(
                'state' => 3 , 'msg' => '报关接口异常' , 'status' => false
            );
        } else {
            switch( $getData['response']['alipay']['records']['customs_declare']['customs_code'] ) {
                case 3 :
                    $return_data = array( 'state' => 4 , 'msg' => '' );
                break;
                case 4 :
                    $return_data = array( 'state' => 3 , 'msg' => '发送海关失败' );
                break;
            }
        }
        return $return_data;
    }

    /**
     * 清关/清关查询加密价签
     */
    private function _querySign() {
        ksort( $this->_data );
        reset( $this->_data );
        $url_data = '';
        foreach( $this->_data as $key => $value ) {
            $url_data[] = "{$key}={$value}";
        }
        $this->_data = implode( '&' , $url_data );
        $this->_data .= '&sign=' . md5( $this->_data . $this->_sign_key );
        $result = $this->_send( 'https://mapi.alipay.com/gateway.do?' . $this->_data.'&sign_type=MD5' );
        $getData = $this->_object_array( simplexml_load_string( $result, 'SimpleXMLElement', LIBXML_NOCDATA ) );
        return $getData;
    }

    /**
     * 对象转换为数组
     * @param  [type] $obj [description]
     * @return [type]      [description]
     */
    private function _object_array($array){
        if(is_object($array)) {  
        $array = (array)$array;  
         } if(is_array($array)) {  
             foreach($array as $key=>$value) {  
                 $array[$key] = $this->_object_array($value);  
                 }  
         }  
         return $array;  
    }

    /**
     * 发送请求
     */
    private function _send( $url ) {
        $ci = curl_init( $url );
        curl_setopt( $ci, CURLOPT_RETURNTRANSFER, true);
        curl_setopt( $ci, CURLOPT_SSL_VERIFYPEER, FALSE); 
        curl_setopt( $ci, CURLOPT_SSL_VERIFYHOST, FALSE);
        $result = curl_exec( $ci );
        $status = curl_getinfo( $ci );
        curl_close($ci);
        return $result;
    }
}

